package com.evil.account.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import com.evil.account.pojo.entity.Enterprise;
import com.evil.account.pojo.entity.User;
import com.evil.account.service.TokenService;
import com.evil.common.core.constant.AppConstant;
import com.evil.common.core.constant.RedisConstant;
import com.evil.common.core.entity.TokenInfo;
import com.evil.common.core.util.RedisKeyUtil;
import com.evil.common.core.util.RedisUtil;
import com.evil.common.core.util.ServletUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * @author liyang
 * @date 2022-08-08 00:00
 */
@Slf4j
@Service
@AllArgsConstructor
public class TokenServiceImpl implements TokenService {

    private final RedisUtil redisUtil;

    /**
     * 创建 token
     *
     * @param user       user
     * @param enterprise enterprise
     * @return token
     */
    @Override
    public String create(User user, Enterprise enterprise) {
        TokenInfo tokenInfo = new TokenInfo();
        tokenInfo.setTel(user.getTel());
        tokenInfo.setUserId(user.getUserId());
        tokenInfo.setUserName(user.getUserName());
        tokenInfo.setNickName(user.getNickName());
        tokenInfo.setEnterpriseId(enterprise.getEnterpriseId());
        tokenInfo.setPlatformType(enterprise.getPlatformType());
        tokenInfo.setCreated(System.currentTimeMillis());

        String token = IdUtil.fastSimpleUUID();

        // 记录用户，登录的token
        redisUtil.set(RedisKeyUtil.accessTokenKey(token), tokenInfo, RedisConstant.TOKEN_EXPIRE_IN_SECOND);
        ServletUtils.getRequest().setAttribute(AppConstant.TOKEN_KEY, token);
        // 用于内部获取该用户登录token
        redisUtil.sSetAndTime(RedisKeyUtil.accessUserTokenKey(user.getUserId()), RedisConstant.TOKEN_EXPIRE_IN_SECOND, token);
        // 记录企业，登录的用户token列表
        redisUtil.sSetAndTime(RedisKeyUtil.accessEnterpriseTokenKey(enterprise.getEnterpriseId(), user.getUserId()), RedisConstant.TOKEN_EXPIRE_IN_SECOND, token);
        return token;
    }

    /**
     * 删除 token
     *
     * @param token token
     */
    @Override
    public void delToken(String token) {
        redisUtil.del(RedisKeyUtil.accessTokenKey(token));
    }

    /**
     * 删除当前用户所有的token
     *
     * @param userId userId
     */
    @Override
    public void delUserToken(Long userId) {
        this.getTokenList(RedisKeyUtil.accessUserTokenKey(userId)).forEach(this::delToken);
    }

    /**
     * 删除企业下某个用户的token
     *
     * @param enterpriseId enterpriseId
     * @param userId       userId
     */
    @Override
    public void delEnterpriseUserToken(Long enterpriseId, Long userId) {
        List<String> enterpriseTokenList = this.getTokenList(RedisKeyUtil.accessEnterpriseTokenKey(enterpriseId, userId));
        if (CollectionUtil.isNotEmpty(enterpriseTokenList)) {
            enterpriseTokenList.forEach(this::delToken);
        }
    }

    /**
     * 切换企业token的处理
     *
     * @param enterpriseId    enterpriseId
     * @param userId          userId
     * @param token           token
     * @param newEnterpriseId newEnterpriseId
     */
    @Override
    public void switchEnterpriseTokenHandler(Long enterpriseId, Long userId, String token, Long newEnterpriseId) {
        // 删除指定原企业的token
        redisUtil.setRemove(RedisKeyUtil.accessEnterpriseTokenKey(enterpriseId, userId), token);
        // token加入到新企业中
        redisUtil.sSetAndTime(RedisKeyUtil.accessEnterpriseTokenKey(newEnterpriseId, userId), RedisConstant.TOKEN_EXPIRE_IN_SECOND, token);
        // 重新设置token的有效时间
        TokenInfo tokenInfo = (TokenInfo) redisUtil.get(RedisKeyUtil.accessTokenKey(token));
        redisUtil.set(RedisKeyUtil.accessTokenKey(token), tokenInfo, RedisConstant.TOKEN_EXPIRE_IN_SECOND);

    }

    /**
     * 获取token列表
     *
     * @param key key
     * @return token列表
     */
    private List<String> getTokenList(String key) {
        List<String> enterpriseTokens = new ArrayList<>();
        Set<Object> enterpriseTokenSet = redisUtil.sGet(key);
        if (CollectionUtil.isNotEmpty(enterpriseTokenSet)) {
            for (Object o : enterpriseTokenSet) {
                String token = (String) o;
                enterpriseTokens.add(token);
            }
        }
        return enterpriseTokens;
    }
}
